package cn.virens.web.components.beetl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import org.beetl.core.Configuration;
import org.beetl.core.Format;
import org.beetl.core.Function;
import org.beetl.core.GroupTemplate;
import org.beetl.core.TagFactory;
import org.beetl.core.VirtualAttributeEval;
import org.beetl.core.VirtualClassAttribute;
import org.beetl.core.resource.WebAppResourceLoader;
import org.beetl.ext.spring.BeetlGroupUtilConfiguration;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.support.PropertiesLoaderUtils;

public class BeetlGroupUtilConfigurationBean extends BeetlGroupUtilConfiguration implements InitializingBean {
	/** 自定义格式化器 */
	private Map<String, Format> formats = new HashMap<>();
	/** 自定义函数 */
	private Map<String, Function> functions = new HashMap<>();
	/** 自定义类型默认格式化器 */
	private Map<Class<?>, Format> typeFormats = new HashMap<>();
	/** 自定义标签 */
	private Map<String, TagFactory> tagFactorys = new HashMap<>();
	/** 自定义函数包 */
	private Map<String, Object> functionPackages = new HashMap<>();
	/** 自定义虚拟属性 */
	private Map<Class<?>, VirtualClassAttribute> virtualClassAttributes = new HashMap<>();
	/** 自定义虚拟属性执行器 */
	private List<VirtualAttributeEval> virtualAttributeEvals = new ArrayList<>();

	@Override
	public void init() {
	}

	/**
	 * 添加 配置信息
	 * 
	 * @param key
	 * @param value
	 */
	public void putPropertie(String key, String value) {
		if (configProperties == null) {
			this.configProperties = new Properties();
		}

		this.configProperties.put(key, value);
	}

	/**
	 * 添加 共享变量
	 * 
	 * @param key
	 * @param value
	 */
	public void putSharedVar(String key, Object value) {
		if (sharedVars == null) {
			this.sharedVars = new HashMap<>();
		}

		this.sharedVars.put(key, value);
	}

	/**
	 * 自定义格式化器
	 *
	 * @param formats
	 */
	@Override
	public void setFormats(Map<String, Format> formats) {
		this.formats = formats;
	}

	/**
	 * 注册 自定义格式化器
	 * 
	 * @param name
	 * @param format
	 */
	public void registerFormat(String name, Format format) {
		this.formats.put(name, format);
	}

	/**
	 * 自定义函数
	 *
	 * @param functions
	 */
	@Override
	public void setFunctions(Map<String, Function> functions) {
		this.functions = functions;
	}

	/**
	 * 注册 自定义函数
	 * 
	 * @param name
	 * @param function
	 */
	public void registerFunction(String name, Function function) {
		this.functions.put(name, function);
	}

	/**
	 * 自定义类型默认格式化器
	 *
	 * @param typeFormats
	 */
	@Override
	public void setTypeFormats(Map<Class<?>, Format> typeFormats) {
		this.typeFormats = typeFormats;
	}

	/**
	 * 注册 自定义类型默认格式化器
	 * 
	 * @param clazz
	 * @param typeFormat
	 */
	public void registerTypeFormat(Class<?> clazz, Format typeFormat) {
		this.typeFormats.put(clazz, typeFormat);
	}

	/**
	 * 自定义标签
	 *
	 * @param tagFactorys
	 */
	@Override
	public void setTagFactorys(Map<String, TagFactory> tagFactorys) {
		this.tagFactorys = tagFactorys;
	}

	/**
	 * 注册 自定义标签
	 * 
	 * @param name
	 * @param tagFactory
	 */
	public void registerTagFactory(String name, TagFactory tagFactory) {
		this.tagFactorys.put(name, tagFactory);
	}

	/**
	 * 自定义函数包
	 *
	 * @param functionPackages
	 */
	@Override
	public void setFunctionPackages(Map<String, Object> functionPackages) {
		this.functionPackages = functionPackages;
	}

	/**
	 * 注册 自定义函数包
	 * 
	 * @param name
	 * @param functionPackage
	 */
	public void registerFunctionPackage(String name, Object functionPackage) {
		this.functionPackages.put(name, functionPackage);
	}

	/**
	 * 自定义虚拟属性
	 *
	 * @param virtualClassAttributes
	 */
	@Override
	public void setVirtualClassAttributes(Map<Class<?>, VirtualClassAttribute> virtualClassAttributes) {
		this.virtualClassAttributes = virtualClassAttributes;
	}

	/**
	 * 注册 自定义虚拟属性
	 * 
	 * @param clazz
	 * @param virtualClassAttribute
	 */
	public void registerVirtualClassAttribute(Class<?> clazz, VirtualClassAttribute virtualClassAttribute) {
		this.virtualClassAttributes.put(clazz, virtualClassAttribute);
	}

	/**
	 * 自定义虚拟属性执行器
	 *
	 * @param virtualAttributeEvals
	 */
	@Override
	public void setVirtualAttributeEvals(List<VirtualAttributeEval> virtualAttributeEvals) {
		this.virtualAttributeEvals = virtualAttributeEvals;
	}

	/**
	 * 添加 自定义虚拟属性执行器
	 * 
	 * @param virtualAttributeEval
	 */
	public void registerVirtualAttributeEval(VirtualAttributeEval virtualAttributeEval) {
		this.virtualAttributeEvals.add(virtualAttributeEval);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		// 如果未指定，返回
		if (this.resourceLoader != null) {
			this.groupTemplate = new GroupTemplate(resourceLoader, initConfiguration());
		} else {
			this.groupTemplate = new GroupTemplate(new WebAppResourceLoader(root), initConfiguration());
		}

		// 设置异常处理器
		if (this.errorHandler != null) {
			this.groupTemplate.setErrorHandler(errorHandler);
		}

		// 设置共享变量
		if (this.sharedVars != null) {
			this.groupTemplate.setSharedVars(sharedVars);
		}

		// 注册自定义格式化器
		for (Entry<String, Format> entry : formats.entrySet()) {
			this.groupTemplate.registerFormat(entry.getKey(), entry.getValue());
		}

		// 注册自定义函数
		for (Entry<String, Function> entry : functions.entrySet()) {
			this.groupTemplate.registerFunction(entry.getKey(), entry.getValue());
		}

		// 注册自定义类型默认格式化器
		for (Entry<Class<?>, Format> entry : typeFormats.entrySet()) {
			this.groupTemplate.registerDefaultFormat(entry.getKey(), entry.getValue());
		}

		// 注册自定义标签
		for (Entry<String, TagFactory> entry : tagFactorys.entrySet()) {
			this.groupTemplate.registerTagFactory(entry.getKey(), entry.getValue());
		}

		// 注册自定义函数包
		for (Entry<String, Object> entry : functionPackages.entrySet()) {
			this.groupTemplate.registerFunctionPackage(entry.getKey(), entry.getValue());
		}

		// 自定义虚拟属性
		for (Entry<Class<?>, VirtualClassAttribute> entry : virtualClassAttributes.entrySet()) {
			this.groupTemplate.registerVirtualAttributeClass(entry.getKey(), entry.getValue());
		}

		// 自定义虚拟属性执行器
		for (VirtualAttributeEval virtualAttributeEval : virtualAttributeEvals) {
			this.groupTemplate.registerVirtualAttributeEval(virtualAttributeEval);
		}
	}

	private Configuration initConfiguration() throws IOException {
		Properties properties = new Properties();

		// 如果指定了配置文件就加载配置文件
		if (this.configFileResource != null) {
			PropertiesLoaderUtils.fillProperties(properties, configFileResource);
		}

		// 如果未手动配置就生成空配置
		if (this.configProperties != null) {
			for (Entry<Object, Object> entry : configProperties.entrySet()) {
				properties.put(entry.getKey(), entry.getValue());
			}
		}

		return new Configuration(properties);
	}
}
